package YAPserver.logic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import YAPenvironment.YAPconstant;
import YAPserver.gameObjects.GameBall;
import YAPserver.gameObjects.Mod;
import YAPserver.gameObjects.Point;
import YAPserver.gameObjects.Slider;
import YAPserver.gameObjects.GameWall;
import YAPserver.mods.list.*;
/**
 * The classic model, by which most games are played. As of yet it is not possible to choose a different model as a client,
 * but that will hopefully be implemented in the next version of YAP. 
 * <p>
 * When a ball is created it has a random direction but its speed and radius are defined using {@link YAPconstant}.
 * The number of ticks required before a mod is created is a random number between 200 and 300. Note that all speeds and timers are normalised to 30fps.
 * In reality the number of ticks could be higher or lower than what is coded.
 * @author Daniel
 *
 */
public class ClassicModel extends AbstractModel {

	private int m_minTicks = (int) Math.round(Game.m_fps*200/30.); //minimum number of ticks until a new mod is created
	private int m_tickDeviation = (int) Math.round(Game.m_fps*100/30.); //max deviation of tick time
	
	private Point m_startPoint = new Point(300, 300);
	private Random rand = new Random();
	private ModGroup m_modList;
	private int m_ticksBall = 0;
	private int m_totalTicks = 0;
	private double maxBallSpeed = 8;
	private boolean timerOn = true;
	/**
	 * Constructs the StandardModel.
	 */
	public ClassicModel(){
		super();
		m_ticks = (int) Math.round(Game.m_fps*250/30.);
		m_maxMods = 5;
		m_ballSpeed = 0.003 * 30./Game.m_fps;
		m_modSpeed = 0.003 * 30./Game.m_fps;
		m_modList = new ClassicMods();
		
		defaultBallSpeed = YAPconstant.C_BALLSTARTSPEED;
		defaultBallRadius = YAPconstant.C_BALLRADIUS;
		defaultModSpeed = YAPconstant.C_BALLSTARTSPEED;
		defaultModRadius = YAPconstant.C_BALLRADIUS;
	}
	@Override
	//later this will be implemented in StandardAbstract
	public void assignPlayers(HashMap<Integer, Player> players,
			ArrayList<Slider> sliders, ArrayList<GameWall> walls) {
		//default
		int i = 0;
		for(int id : players.keySet()){
			//first create sliders
			//then assign the walls and sliders to the player
			sliders.add(new Slider(walls.get(i)));
			players.get(id).setWallAndSlider(walls.get(i),sliders.get(i));
			i++;
		}
	}
	
	@Override
	public void addBall(ArrayList<GameBall> balls) {
		double angle = rand.nextDouble()*2*Math.PI;
		balls.add(new GameBall(new Point(m_startPoint), angle,
				defaultBallSpeed, defaultBallRadius));
	}

	@Override
	public void createMod(ArrayList<Mod> modsMoving, GameModifier gameMod) {
		double angle = rand.nextDouble()*2*Math.PI;
		modsMoving.add(new Mod(new Point(m_startPoint), angle, defaultModSpeed, defaultModRadius, gameMod, m_modList.randomMod()));
	}

	@Override
	public void moveBalls(ArrayList<GameBall> balls, ArrayList<Mod> modsMoving) {
		//this method is called once per round
		m_ticksBall++;
		m_totalTicks++;
		if(30*m_ticksBall/Game.m_fps > 900 /*roughly 30s*/){
//			System.out.println(Math.round(m_totalTicks/Game.m_fps)+"s");
			m_ticksBall=0;
			if(timerOn){
				ModGroup meanMods = new ClassicMeanMods();
				if(defaultBallSpeed < maxBallSpeed){
					defaultBallSpeed = defaultBallSpeed + 1;
				}
					if(30*m_totalTicks/Game.m_fps < 9000){
					m_modList.add(meanMods.randomMod());
					m_modList.add(meanMods.randomMod());
					m_modList.add(meanMods.randomMod());
				}
				if(30*m_totalTicks/Game.m_fps > 9000 /*roughly 5 min*/){
					m_modList = new ClassicMeanMods();
					timerOn = false;
				}
			}
				
			
		}
		double speed=0;
		for(int i=0; i<balls.size(); i++){
			balls.get(i).move();
			speed = balls.get(i).getSpeed();
			balls.get(i).setSpeed(speed + m_ballSpeed);
		}
		for(int i=0; i<modsMoving.size(); i++){
			modsMoving.get(i).move();
			speed = modsMoving.get(i).getSpeed();
			modsMoving.get(i).setSpeed(speed + m_modSpeed);
		}
	}
	@Override
	void resetTicks() {
		m_ticks = rand.nextInt(m_tickDeviation) + m_minTicks;	
	}

}
